{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Brief Intro to pydeck\n",
    "\n",
    "pydeck is made for visualizing data points in 2D or 3D maps. Specifically, it handles\n",
    "\n",
    "- rendering large (>1M points) data sets, like LIDAR point clouds or GPS pings\n",
    "- large-scale updates to data points, like plotting points with motion\n",
    "- making beautiful maps\n",
    "\n",
    "Under the hood, it's powered by the [deck.gl](https://github.com/uber/deck.gl/) JavaScript framework.\n",
    "\n",
    "pydeck is strongest when used in tandem with [Pandas](https://pandas.pydata.org/) but doesn't have to be.\n",
    "\n",
    "Please note that **these demo notebooks are best when executed cell-by-cell**, so ideally clone this repo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pydeck as pdk"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# There are three steps for most pydeck visualizations\n",
    "\n",
    "We'll walk through pydeck using a visualization of vehicle accident data in the United Kingdom.\n",
    "\n",
    "## 1. Choose your data\n",
    "\n",
    "Here, we'll use the history of accident data throughout the United Kingdom. This data set presents the location of every latitude and longitude of car accidents in the UK in 2014 ([source](https://data.gov.uk/dataset/053a6529-6c8c-42ac-ae1e-455b2708e535/road-traffic-accidents))."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "UK_ACCIDENTS_DATA = 'https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv'\n",
    "\n",
    "pd.read_csv(UK_ACCIDENTS_DATA).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Configure the visualization: Choose your layer(s) and viewport\n",
    "\n",
    "pydeck's **`Layer`** object takes two positional and many keyword arguments:\n",
    "\n",
    "- First, a string specifying the layer type, with our example below using `'HexagonLayer'`\n",
    "- Next, a data URL–below you'll see the `UK_ACCIDENTS_DATA` that we set above, but we could alternately pass a data frame or list of dictionaries\n",
    "- Finally, keywords representing that layer's attributes–in our example, this would include `elevation_scale`, `elevation_range`, `extruded`, `coverage`.\n",
    "\n",
    "```python\n",
    "layer = pdk.Layer(\n",
    "    'HexagonLayer',\n",
    "    UK_ACCIDENTS_DATA,\n",
    "    elevation_scale=50,\n",
    "    elevation_range=[0, 3000],\n",
    "    extruded=True,                 \n",
    "    coverage=1)\n",
    "```\n",
    "\n",
    "There is of course an entire catalog of layers which you're welcome to check out within the [deck.gl documentation](https://deck.gl/#/documentation/deckgl-api-reference/layers/overview).\n",
    "\n",
    "### Configure your viewport\n",
    "\n",
    "We also have to specifiy a **`ViewState`** object.\n",
    "\n",
    "The **`ViewState`** object specifies a camera angle relative to the map data. If you don't want to manually specify it, the function **`pydeck.data_utils.autocompute_viewport`** can take your data and automatically zoom to it.\n",
    "\n",
    "pydeck also provides some controls, most of which should be familiar from map applications throughout the web. By default, you can hold out and drag to rotate the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "layer = pdk.Layer(\n",
    "    'HexagonLayer',\n",
    "    UK_ACCIDENTS_DATA,\n",
    "    get_position='-',\n",
    "    elevation_scale=50,\n",
    "    elevation_range=[0, 3000],\n",
    "    extruded=True,                 \n",
    "    coverage=1)\n",
    "\n",
    "# Set the viewport location\n",
    "view_state = pdk.ViewState(\n",
    "    longitude=-1.415,\n",
    "    latitude=52.2323,\n",
    "    zoom=6,\n",
    "    min_zoom=5,\n",
    "    max_zoom=15,\n",
    "    pitch=40.5,\n",
    "    bearing=-27.396)\n",
    "\n",
    "# Combined all of it and render a viewport\n",
    "r = pdk.Deck(layers=[layer], initial_view_state=view_state)\n",
    "r.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render an update to the visualization\n",
    "\n",
    "Execute the cell below and look at the map in the cell above–you'll notice a seamless rendered update on the map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.elevation_range = [0, 5000]\n",
    "r.update()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Support updates over time\n",
    "\n",
    "We can combine any Python function with our work here, of course. Execute the cell below to update our map above over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "for i in range(0, 10000, 1000):\n",
    "    layer.elevation_range = [0, i]\n",
    "    r.update()\n",
    "    time.sleep(0.1)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {
     "3b9786c3664248aeb722a1086e848318": {
      "model_module": "@deck.gl/jupyter-widget",
      "model_module_version": "^7.1.0-alpha.1",
      "model_name": "DeckGLModel",
      "state": {
       "_model_module_version": "^7.1.0-alpha.1",
       "_view_module_version": "^7.1.0-alpha.1",
       "json_input": "{\"initialViewState\": {\"bearing\": -27.396, \"latitude\": 52.2323, \"longitude\": -1.415, \"maxZoom\": 15, \"minZoom\": 5, \"pitch\": 40.5, \"zoom\": 6.6}, \"layers\": [{\"colorRange\": [[1, 152, 189], [73, 227, 206], [216, 254, 181], [254, 237, 177], [254, 173, 84], [209, 55, 78]], \"coverage\": 1, \"data\": \"https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv\", \"elevationRange\": [0, 3000], \"elevationScale\": 50, \"extruded\": true, \"getPosition\": \"-\", \"getRadius\": 1000, \"id\": \"71799c82-d104-4ca1-8d02-b5d48460708c\", \"lightSettings\": {\"ambientRatio\": 0.7, \"diffuseRatio\": 0.6, \"lightsPosition\": [-0.144528, 49.739968, 8000, -3.807751, 54.104682, 10000], \"numberOfLights\": 2}, \"opacity\": 1, \"radius\": 1000, \"type\": \"HexagonLayer\", \"upperPercentile\": 100}], \"mapStyle\": \"mapbox://styles/mapbox/dark-v9\", \"views\": [{\"controller\": true, \"type\": \"MapView\"}]}",
       "layout": "IPY_MODEL_c93002f6c4a842e9bc47cba1f0a47022",
       "mapbox_key": "pk.eyJ1IjoiZHViZXJzYWoyIiwiYSI6ImNqcHhmYzcwNTBrZHc0OW9udGljMm1pNXQifQ.DxYvaredXVDkvS0nSAuf_Q"
      }
     },
     "55a8acca3fa64c49b8c2b76dc260a8d3": {
      "model_module": "@deck.gl/jupyter-widget",
      "model_module_version": "^7.1.0-alpha.1",
      "model_name": "DeckGLModel",
      "state": {
       "_model_module_version": "^7.1.0-alpha.1",
       "_view_module_version": "^7.1.0-alpha.1",
       "json_input": "{\"initialViewState\": {\"bearing\": -27.396, \"latitude\": 52.2323, \"longitude\": -1.415, \"maxZoom\": 15, \"minZoom\": 5, \"pitch\": 40.5, \"zoom\": 6}, \"layers\": [{\"colorRange\": [[1, 152, 189], [73, 227, 206], [216, 254, 181], [254, 237, 177], [254, 173, 84], [209, 55, 78]], \"coverage\": 1, \"data\": \"https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv\", \"elevationRange\": [0, 9000], \"elevationScale\": 50, \"extruded\": true, \"getPosition\": \"-\", \"getRadius\": 1000, \"id\": \"24807c08-e7be-4aa4-8575-5462f16c6313\", \"opacity\": 1, \"radius\": 1000, \"type\": \"HexagonLayer\", \"upperPercentile\": 100}], \"mapStyle\": \"mapbox://styles/mapbox/dark-v9\", \"views\": [{\"controller\": true, \"type\": \"MapView\"}]}",
       "layout": "IPY_MODEL_cfb0222b37ef4555b285b0c42ff0a0e8",
       "mapbox_key": "pk.eyJ1IjoiZHViZXJzYWoyIiwiYSI6ImNqcHhmYzcwNTBrZHc0OW9udGljMm1pNXQifQ.DxYvaredXVDkvS0nSAuf_Q"
      }
     },
     "5654614a55664d91a75ad631467d2511": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.1.0",
      "model_name": "LayoutModel",
      "state": {}
     },
     "89e5bc7802ef460d8e03ab16fcfe0adf": {
      "model_module": "@deck.gl/jupyter-widget",
      "model_module_version": "^7.1.0-alpha.1",
      "model_name": "DeckGLModel",
      "state": {
       "_model_module_version": "^7.1.0-alpha.1",
       "_view_module_version": "^7.1.0-alpha.1",
       "json_input": "{\"initialViewState\": {\"bearing\": -27.396, \"latitude\": 52.2323, \"longitude\": -1.415, \"maxZoom\": 15, \"minZoom\": 5, \"pitch\": 40.5, \"zoom\": 6.6}, \"layers\": [{\"colorRange\": [[1, 152, 189], [73, 227, 206], [216, 254, 181], [254, 237, 177], [254, 173, 84], [209, 55, 78]], \"coverage\": 1, \"data\": \"https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv\", \"elevationRange\": [0, 3000], \"elevationScale\": 50, \"extruded\": true, \"getPosition\": \"-\", \"getRadius\": 1000, \"id\": \"61da0d21-e44c-4c15-8c56-e8f6555f5675\", \"opacity\": 1, \"radius\": 1000, \"type\": \"HexagonLayer\", \"upperPercentile\": 100}], \"mapStyle\": \"mapbox://styles/mapbox/dark-v9\", \"views\": [{\"controller\": true, \"type\": \"MapView\"}]}",
       "layout": "IPY_MODEL_5654614a55664d91a75ad631467d2511",
       "mapbox_key": "pk.eyJ1IjoiZHViZXJzYWoyIiwiYSI6ImNqcHhmYzcwNTBrZHc0OW9udGljMm1pNXQifQ.DxYvaredXVDkvS0nSAuf_Q"
      }
     },
     "c93002f6c4a842e9bc47cba1f0a47022": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.1.0",
      "model_name": "LayoutModel",
      "state": {}
     },
     "cfb0222b37ef4555b285b0c42ff0a0e8": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.1.0",
      "model_name": "LayoutModel",
      "state": {}
     }
    },
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
